package torres.entity;

import java.util.*;

import torres.fileIO.BasicContainer;
import torres.ability.Ability;
import torres.ability.AbilityManager;
import torres.action.Effect;
import torres.fileIO.ClassContainer;
import torres.item.WeaponType;

/**
 * @author Torres
 * A specific Occupation that specializes in magical spells.
 * The primary stat of a Sneak is Agility.
 */

public class Summoner implements Occupation {
	private LinkedHashSet<Ability> summonerAbilityList;
	private LinkedHashSet<Ability> attackList;
	private final Stat summonerPrimaryStat = Stat.INTELLECT;
	private final Job job = Job.SUMMONER;
	private double summonerStrengthMultiplier;
	private double summonerAgilityMultiplier;
	private double summonerIntellectMultiplier;
	private int enchantmentSkill;
	private int boonSkill;
	private int baneSkill;
	private int staffSkill;
	private final String name = "Summoner";
	
	/**
	 * Creates a default Summoner 
	 */
	public Summoner() { // Default Constrcutor
		summonerAbilityList = new LinkedHashSet<Ability>();
		//summonerAbilityList.add(ability);
		attackList = new LinkedHashSet<Ability>(3);
		summonerStrengthMultiplier = 1.15;
		summonerAgilityMultiplier = 1.15;
		summonerIntellectMultiplier = 1.3;
	}
	
	/**
	 * Creates a new Summoner with the specified values. 
	 * @param abilityList The ability list.
	 * @param strength The strength multiplier.
	 * @param agility The agility multiplier.
	 * @param intellect The intellect multiplier.
	 */
	public Summoner(LinkedHashSet<Ability> abilityList, double strength, double agility, double intellect) {
		this.summonerAbilityList = abilityList;
		this.summonerStrengthMultiplier = strength;
		this.summonerAgilityMultiplier = agility;
		this.summonerIntellectMultiplier = intellect;
		attackList = new LinkedHashSet<Ability>(3);
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getAgilityMultiplier()
	 */
	public double getAgilityMultiplier() {
		return summonerAgilityMultiplier;
	}
	
	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getIntellectMultiplier()
	 */
	public double getIntellectMultiplier() {
		return summonerIntellectMultiplier;
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getPrimarySkill()
	 */
	public Stat getPrimaryStat() {
		return summonerPrimaryStat;
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getStrengthMultiplier()
	 */
	public double getStrengthMultiplier() {
		return summonerStrengthMultiplier;
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getAbilityList()
	 */
	public LinkedHashSet<Ability> getAbilityList() {
		return summonerAbilityList;
	}
	
	/* (non-Javadoc)
	 * @see torres.entity.Occupation#getJob()
	 */
	public Job getJob() {
		return job;
	}
	
	/**
	 * Sets enchantmentSkill level of Summoner.
	 * @param enchantmentSkill the new enchantmentSkill level to set
	 */
	public void setEnchantmentSkill(int enchantmentSkill) {
		this.enchantmentSkill = enchantmentSkill;
	}

	/**
	 * Returns enchantmentSkill level.
	 * @return the enchantmentSkill
	 */
	public int getEnchantmentSkill() {
		return enchantmentSkill;
	}

	/**
	 * Sets boonSkill level of Summoner.
	 * @param boonSkill the new boonSkill level to set.
	 */
	public void setBoonSkill(int boonSkill) {
		this.boonSkill = boonSkill;
	}

	/**
	 * Returns boonSkill level.
	 * @return the boonSkill
	 */
	public int getBoonSkill() {
		return boonSkill;
	}

	/**
	 * Sets the baneSkill of Summoner.
	 * @param baneSkill the new baneSkill level to set
	 */
	public void setBaneSkill(int baneSkill) {
		this.baneSkill = baneSkill;
	}

	/**
	 * Returns the baneSkill level.
	 * @return the baneSkill
	 */
	public int getBaneSkill() {
		return baneSkill;
	}

	/**
	 * Sets the staffPhysicalSkill level of Summoner.
	 * @param staffPhysicalSkill the new staffPhysicalSkill level to set
	 */
	public void setStaffSkill(int staffPhysicalSkill) {
		this.staffSkill = staffPhysicalSkill;
	}

	/**
	 * Return staffPhysicalSkill level.
	 * @return the staffPhysicalSkill
	 */
	public int getStaffSkill() {
		return staffSkill;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return name;
	}

	/* (non-Javadoc)
	 * @see torres.fileIO.Saveable#save()
	 */
	@Override
	public ClassContainer save() {
		ClassContainer curClass = new ClassContainer("Job");
		ClassContainer curStructure = new ClassContainer("AbilityList");
		/*
		for(Ability ability: summonerAbilityList) {
			curStructure.addProperty(ability.save());
		}
		*/
		curClass.addProperty(curStructure);
		curClass.addProperty(new BasicContainer("summonerStrengthMultiplier", summonerStrengthMultiplier));
		curClass.addProperty(new BasicContainer("summonerAgilityMultiplier", summonerAgilityMultiplier));
		curClass.addProperty(new BasicContainer("summonerIntellectMultiplier", summonerIntellectMultiplier));
		curClass.addProperty(new BasicContainer("enchantmentSkill", enchantmentSkill));
		curClass.addProperty(new BasicContainer("boonSkill", boonSkill));
		curClass.addProperty(new BasicContainer("baneSkill", baneSkill));
		curClass.addProperty(new BasicContainer("staffSkill", staffSkill));
	
		return curClass;
	}

	/* (non-Javadoc)
	 * @see torres.fileIO.Saveable#load(torres.fileIO.ClassContainer)
	 */
	@Override
	public void load(ClassContainer classContainer) {
		BasicContainer summonerStrengthMultiplierCont = (BasicContainer)classContainer.getProperty("summonerStrengthMultiplier");
		summonerStrengthMultiplier = Double.parseDouble((String)summonerStrengthMultiplierCont.getValue());
		BasicContainer summonerAgilityMultiplierCont = (BasicContainer)classContainer.getProperty("summonerAgilityMultiplier");
		summonerAgilityMultiplier = Double.parseDouble((String)summonerAgilityMultiplierCont.getValue());
		BasicContainer summonerIntellectMultiplierCont = (BasicContainer)classContainer.getProperty("summonerIntellectMultiplier");
		summonerIntellectMultiplier = Double.parseDouble((String)summonerIntellectMultiplierCont.getValue());
		BasicContainer enchantmentSkillCont = (BasicContainer)classContainer.getProperty("enchantmentSkill");
		enchantmentSkill = Integer.parseInt((String)enchantmentSkillCont.getValue());
		BasicContainer boonSkillCont = (BasicContainer)classContainer.getProperty("boonSkill");
		boonSkill = Integer.parseInt((String)boonSkillCont.getValue());
		BasicContainer baneSkillCont = (BasicContainer)classContainer.getProperty("baneSkill");
		baneSkill = Integer.parseInt((String)baneSkillCont.getValue());
		BasicContainer staffSkillContainer = (BasicContainer)classContainer.getProperty("staffSkill");
		staffSkill = Integer.parseInt((String)staffSkillContainer.getValue());
		
	}

	/* (non-Javadoc)
	 * @see torres.entity.Occupation#updateAbilityList(int)
	 */
	@Override
	public void updateAbilityList(int level) {
		// TODO Auto-generated method stub
		AbilityManager.getInstance().updateAbilityList(summonerAbilityList, level, this.getJob());
		
	}
	
	@Override
	public boolean allocateSkillPoint(Skill skill) {
		// TODO Auto-generated method stub
		switch(skill) {	
			case ENCHANTMENT : 
				if(enchantmentSkill<35)
					this.enchantmentSkill++; 
				else 
					return false;
				break;
			case BOON : 
				if(boonSkill<35)
					this.boonSkill++; 
				else 
					return false;
				break;
			case BANE : 
				if(baneSkill<35)
					this.baneSkill++; 
				else 
					return false;
				break;
			case STAFF : 
				if(staffSkill<35)
					this.staffSkill++; 
				else 
					return false;
				break;
			default : 
				System.err.println("Summoner.allocateSkillPoint(): " +
						"Skill point was not allocated. Skill: " + skill.toString());
				return false;
		}
		return true;
	}
	
	public LinkedHashSet<String> retreiveSkillList(LinkedHashSet<String> skillList) {
		skillList.add("Enchantment Skill:\t\t\t" + this.enchantmentSkill);
		skillList.add("Boon Skill:\t\t\t" + this.boonSkill);
		skillList.add("Bane Skill:\t\t\t" + this.baneSkill);
		skillList.add("Staff Skill:\t\t\t" + this.staffSkill);
		return skillList;
	}
	
	@Override
	public LinkedHashSet<Skill> retreiveSkillEnumList(LinkedHashSet<Skill> hashSet) {
		hashSet.add(Skill.ENCHANTMENT);
		hashSet.add(Skill.BOON);
		hashSet.add(Skill.BANE);
		hashSet.add(Skill.STAFF);
		return hashSet;
	}
	
	public void moveHook(Entity e) {
		//this method left intentionally (almost) blank 
	}

	/**
	 * @return the summonerAttackList
	 */
	public LinkedHashSet<Ability> getAttackList() {
		return attackList;
	}
	
	public boolean canEquip(WeaponType type) {
		switch(type) {
			case ONE_HANDED:
			case TWO_HANDED:
			case BRAWLING:
			case RANGED: return false;
			case STAFF: return true;
		}
		return false;
	}
	
	public int getStaffSkillBonus(){
		
		return (100 + (staffSkill));
	}
	
	public double applySkill(Effect e) {
		double multiplier = 1.0;
		switch(e) {
			case FIRE:
			case WATER:
			case AIR:
			case LIGHTNING:
				multiplier = 1.0 + (this.getBaneSkill()/5.0);
				break;
			case HEAL:
			case MANA:
			case BUFF_FIRE:
			case BUFF_STR:
				multiplier = 1.0 + (this.getBoonSkill()/5.0);
				break;
			case SLEEP:
			case CHARM:
				multiplier = 1.0 + (this.getEnchantmentSkill()/5.0);
			
		}
		return multiplier;
	}
}
